---
title: SAIF.Application security and authorization
summary: Authorization requirements, AD resource groups, security enforcement points, and data-level access control.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-08-21
library: SAIF.Application
reference_type: embedded
---

# SAIF.Application security and authorization

This page documents authorization mechanisms implemented or consumed by this library. Authentication is handled entirely by infrastructure (NTLM/AD) and is not application-level — all code receives a `WindowsIdentity`-backed `clsSecurityPrincipal` on the request context, and no authentication code exists in this library.

## Authorization architecture

`SAIF.Application` is a **delegated / pass-through** authorization layer: it caches and exposes decisions produced by the BOF framework's `clsSecurityPrincipal.IsAuthorized`, and performs no AD, LDAP, or WCF call itself. The library declares zero AD resource names — resource names travel in as method parameters (`UserAccess.HasAccess(inResourceName)`, `UserAccess.CheckAccess(ParamArray inResourceName())`) and are forwarded verbatim to the framework principal, so this library supplies the *mechanism* (identity binding, decision caching, tri-state access classification, deny-by-default) but no *policy*.

```mermaid
flowchart TD
    Deriv["Derived manager / access<br>class"] --> UA[UserAccess.HasAccess]
    UA --> Cache{Cached?}
    Cache -->|Yes| Return[Return cached Boolean]
    Cache -->|No| SP[clsSecurityPrincipal.IsAuthorized]
    SP --> AD[(AD group check<br>implementation opaque)]
    AD --> Return
```

Whether `clsSecurityPrincipal.IsAuthorized` internally performs a WCF `SecurityService` hop, a direct AD lookup, or a process-level cached lookup cannot be confirmed from this repository — the implementation lives in the external `SAIF.BOF.Framework` 2.0.22279.1 package, which is not available locally.**

## AD resource catalog

**None.** `SAIF.Application` declares zero AD resource names. Every source file was scanned for resource-name string literals, `*SECURITYKEY` / `*Resource` constants, LDAP paths, and attribute parameters; no match exists.

| Resource name | Purpose | Enforcement point | Source |
| --- | --- | --- | --- |
| — (none declared) | — | — | — |

Resource names that flow *through* this library are declared by consumers in the same repository and belong to their own libraries' documentation, not to `SAIF.Application`: `SecureClaim`, `ConflictClaim`, `ExposureClaim`, `CollateralHealthClaim` (`SAIF.Application.Claim/ClaimUserAccess.vb`); `LNConflict`, `LNExposure`, `LNAdmin`, `LNCaseUpdate`, `LNView` (`SAIF.Application.Claim.Legal/LegalManagerBase.vb`); `LNNoteView`, `LNUpdate` (`SAIF.Application.Claim.Legal/LegalNet/clsCaseNotesManager.vb`); `LNLCEUpdate`, `LNDueDateUpdate` (`SAIF.Application.Claim.Legal/LegalNet/clsScheduleManager.vb`).

## Authorization enforcement points

### Attribute-based authorization

**None.** No `<SAIFAuthorize>`, `<SaifAuthorize>`, `<Authorize>`, or any type inheriting `AuthorizeAttribute` appears in `SAIF.Application`; the library is a non-web class library.

### Programmatic authorization checks

| Class | Method | Resource / Role | Check type | Source |
| --- | --- | --- | --- | --- |
| `UserAccess` | `HasAccess(inResourceName As String) As Boolean` | caller-supplied resource name | Decision point — cache probe on `m_AccessControl(inResourceName.ToLower)`; on miss calls `m_Principal.IsAuthorized(inResourceName)` and caches the Boolean. The only call site in the library that actually asks for an authorization decision. | `SAIF.Application/UserAccess.vb` |
| `UserAccess` | `CheckAccess(ParamArray inResourceName As String())` | caller-supplied resource names | Cache warm-up — loops the names calling `HasAccess`; the loop result is discarded, so nothing is returned to the caller and no denial is raised. | `SAIF.Application/UserAccess.vb` |
| `UserAccess` | `SetPrincipal(inPrincipal As clsSecurityPrincipal)` (`Protected`) | — | Identity binding — injects the principal whose authorizations are evaluated. `m_Principal` has no default; calling `HasAccess` before `SetPrincipal` throws `NullReferenceException` (fail-closed by exception, not by explicit denial). | `SAIF.Application/UserAccess.vb` |
| `AppManagerBase` | `New(inSecurityPrincipal As clsSecurityPrincipal)` (`Protected`, only constructor) | — | Identity binding / precondition — no manager instance can exist without an identity ([BR-APP-001](business-rules.md#br-app-001-manager-construction-requires-a-security-principal)). | `SAIF.Application/AppManagerBase.vb` |
| `AppManagerBase` | `OnCheckSecurity()` (`Protected MustOverride`) | — | Enforcement hook — the contractual place where a derived manager translates resource access into an `AppSecurityRole`. Declared but never invoked from within this library; invocation is the derived manager's responsibility. | `SAIF.Application/AppManagerBase.vb` |
| `AppManagerBase` | `MarkUpdate()` / `MarkViewOnly()` / `MarkNoAccess()` (`Protected`) | — | Decision recording — the only writers of `m_AppSecurityRole`. `SecurityRole` and the derived `Is*` properties are read-only, so no external caller can elevate its own rights ([BR-APP-003](business-rules.md#br-app-003-access-classification-is-mutually-exclusive-and-read-only-externally)). | `SAIF.Application/AppManagerBase.vb` |

**Count:** 6 programmatic enforcement points, 0 attribute-based.

## Data-level authorization

**None found in this library.** No `CheckValidContext`, `IsValidPolicyForCurrentUser`, `ValidateOwnership`, `IsExternal`, or equivalent ownership-validation member exists. `ApplicationDataAccess` only builds connection environments and data portals; it issues no query and applies no row filter. `AppManagerBase.ValidContext` / `OnValidContext()` is the declared hook for context validation — it is `MustOverride` and never called from within this library, so any ownership check it eventually performs is authored by the derived manager.

Security-adjacent (audit, not authorization): the database client identity is derived from the authenticated user — `AppManagerBase.DataLayer` lazily constructs `New ApplicationDataAccess(SecurityPrincipal.UserName.ToString)`, and `ApplicationDataAccess.New` sets `m_Env.ClientID = inBatchUserID` when a non-empty id is supplied. `CreateSQLServerPortal` / `CreateOraclePortal` override `ClientID` with `BatchID` when non-blank ([BR-APP-007](business-rules.md#br-app-007-database-client-identity-is-the-requesting-user-unless-overridden)). This is an attribution/traceability control, not an access-control check — nothing is denied on its basis. The `BatchID` property is `Public` read/write with no guard, so a caller can freely change the DB client identity; this is impersonation-for-auditing only and does not affect AD authorization.

## Segregation of duties

**None found.** No `*SegregationOfDuties*` / `*SOD*` type or member exists in `SAIF.Application`. The only mutual exclusivity present is the `AppSecurityRole` tri-state ([BR-APP-003](business-rules.md#br-app-003-access-classification-is-mutually-exclusive-and-read-only-externally)), which is an access-classification invariant, not a segregation-of-duties control.

## Security interfaces and contracts

| Interface / Class | Role | Consumers | Source |
| --- | --- | --- | --- |
| `clsSecurityPrincipal` | External authorization decision source (namespace `SAIF.Framework.Security`, package `SAIF.BOF.Framework` 2.0.22279.1) | `UserAccess`, `AppManagerBase.SecurityPrincipal` | `SAIF.Application/UserAccess.vb`, `SAIF.Application/AppManagerBase.vb` |
| `UserAccess` | Authorization-decision cache boundary consumed by domain access classes | `SAIF.Application.Claim/ClaimUserAccess.vb` (`Inherits UserAccess`) | `SAIF.Application/UserAccess.vb` |
| `AppManagerBase` | Security-aware manager base exposing `SecurityPrincipal` (`Protected ReadOnly`) to derived managers only | `SAIF.Application.Claim/ClaimAppManager.vb`, `SAIF.Application.Claim.Legal/LegalManagerBase.vb` | `SAIF.Application/AppManagerBase.vb` |

## Security architecture summary

| Metric | Value |
| --- | --- |
| Authorization architecture type | Delegated / pass-through |
| Total AD resource names referenced | 0 |
| Authorization enforcement points — attribute-based | 0 |
| Authorization enforcement points — programmatic | 6 |
| Data-level (ownership) authorization checks | 0 |
| Segregation of duties (SOD) rules | 0 |
| Machine/application authorization present | No |
| Security manager implementations | 0 (no `ISecurityManager`, `IDomainSecurityManager`, `SecurityManager`, `DomainSecurityManagerBase`) |
| Directory-services usage | None (no `System.DirectoryServices`, `PrincipalContext`, `GroupPrincipal`, `DirectoryEntry`, `DirectorySearcher`, or LDAP literal) |
| Security types consumed | `clsSecurityPrincipal` (`SAIF.Framework.Security`, package `SAIF.BOF.Framework` 2.0.22279.1), imported project-wide via `<Import Include="SAIF.Framework.Security" />` |
| Caching model | Per-`UserAccess`-instance `SortedList(Of String, Boolean)` keyed on the lower-cased resource name; a mid-session AD group change is not observed until a new instance is created ([BR-APP-004](business-rules.md#br-app-004-ad-resource-authorization-is-cached-per-instance)) |
| Default posture | Deny by default (`NoAccess` initial state; empty cache forces a real `IsAuthorized` call on first ask) |
| WCF SecurityService integration | None in this library — no service reference, endpoint URL, or `IsAuthorized2` call; any WCF hop occurs inside `clsSecurityPrincipal.IsAuthorized`.** |

**Coverage assessment.** `SAIF.Application` supplies the mechanism (identity binding, decision caching, tri-state access classification, deny-by-default) but contains no policy. All policy — which resource guards which capability — is expressed one layer up, in `SAIF.Application.Claim` and `SAIF.Application.Claim.Legal`.

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts. Statements marked with `**` could not be confirmed; treat
> as unknown until verified.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)

## Sources
- `SAIF.Application/UserAccess.vb`
- `SAIF.Application/AppManagerBase.vb`
- `SAIF.Application/Enums.vb`
- `SAIF.Application/ApplicationDataAccess.vb`
- `SAIF.Application/SAIF.Application.vbproj`
- `SAIF.Application.Claim/ClaimUserAccess.vb`
- `SAIF.Application.Claim.Legal/LegalManagerBase.vb`
- `SAIF.Application.Claim.Legal/LegalNet/clsCaseNotesManager.vb`
- `SAIF.Application.Claim.Legal/LegalNet/clsScheduleManager.vb`
